﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RedmineWorkerDotNET.App.Classes;
using System.Collections.Specialized;
using Redmine.Net.Api.Types;
using RedmineWorkerDotNET.App.Controls;

namespace RedmineWorkerDotNET.App.Forms
{
    public partial class FormIssues : Form
    {
        #region Initialization

        public FormIssues()
        {
            UIConfigSaver.AttachPositionerToForm(this, LoadSettings, SaveSettings);

            InitializeComponent();

            grdIssues.AutoGenerateColumns = false;
        }

        private void FormIssues_Load(object sender, EventArgs e)
        {
            // Verifica se esta logado
            if (RedmineClient.User == null)
            {
                FormLogin frmLogin = new FormLogin();
                DialogResult objResult = frmLogin.ShowDialog(this);

                if (objResult != System.Windows.Forms.DialogResult.OK)
                {
                    DialogResult = DialogResult.Cancel;
                    Application.Exit();
                    return;
                }
            }

            ReloadIssues();
        } 

        #endregion

        #region Reload Issues Methods

        private void ReloadIssues()
        {
            BackgroundWorker objReloadIssuesWorker = new BackgroundWorker();
            objReloadIssuesWorker.DoWork += new DoWorkEventHandler(objReloadIssuesWorker_DoWork);
            objReloadIssuesWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(objReloadIssuesWorker_RunWorkerCompleted);
            objReloadIssuesWorker.RunWorkerAsync();
        }

        private void objReloadIssuesWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var parameters = new NameValueCollection { 
                { "assigned_to_id", "me" } ,{ "status_id", "open" }, {"limit", "100"} };

            IList<Issue> lstIssues = RedmineClient.Manager.GetObjectList<Issue>(parameters);
            Dictionary<int, Issue> mapDictionary = new Dictionary<int, Issue>();
            foreach (Issue objIssue in lstIssues)
            {
                mapDictionary[objIssue.Id] = objIssue;
            }

            foreach (Issue objIssue in lstIssues)
            {
                if (objIssue.Parent != null && objIssue.Parent.Id > 0)
                {
                    if (!mapDictionary.ContainsKey(objIssue.Parent.Id))
                        mapDictionary[objIssue.Parent.Id] = RedmineClient.Manager.GetObject<Issue>(objIssue.Parent.Id.ToString(), null);

                    objIssue.Parent.Name = mapDictionary[objIssue.Parent.Id].Subject;
                }
            }

            e.Result = lstIssues;
        }

        private void objReloadIssuesWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                // TODO
            }
            else
            {
                DataGridViewColumn objSortedColumn = GetSortedColumn();

                int iSortedColumnIndex = -1;
                SortOrder objCurrentOrder = SortOrder.None;
                if (objSortedColumn != null)
                {
                    iSortedColumnIndex = objSortedColumn.Index;
                    objCurrentOrder = objSortedColumn.HeaderCell.SortGlyphDirection;
                    
                    // Inverts the selection to make sure the SortGrid uses the current order
                    objCurrentOrder = objCurrentOrder == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
                }

                SetDataSource(e.Result as IList<Issue>);
            }
        }

        private void SetDataSource(IList<Issue> lstOriginal)
        {
            SimpleFilteredList<ComparableIssue> lstSource = new SimpleFilteredList<ComparableIssue>();
            foreach (Issue objIssue in lstOriginal)
            {
                lstSource.Add(new ComparableIssue(objIssue));
            }

            bindingSource1.DataSource = lstSource;
            grdIssues.DataSource = bindingSource1;
        }

        private DataGridViewColumn GetSortedColumn()
        {
            DataGridViewColumn objSortedColumn = null;
            foreach (DataGridViewColumn objColumn in grdIssues.Columns)
            {
                if (objColumn.HeaderCell.SortGlyphDirection != SortOrder.None)
                {
                    objSortedColumn = objColumn;
                    break;
                }
            }
            return objSortedColumn;
        }

        #endregion

        #region Settings Methods

        private void LoadSettings(UIConfigSaver.WindowPositionSettings objSettings)
        {
            foreach (DataGridViewColumn objColumn in grdIssues.Columns)
            {
                string sColumnWidth = objSettings.GetProperty(objColumn.Name + "_width");
                int iColumnWidth = 0;
                if (sColumnWidth != null && int.TryParse(sColumnWidth, out iColumnWidth))
                    objColumn.Width = iColumnWidth;

                string sColumnSort = objSettings.GetProperty(objColumn.Name + "_sort");
                SortOrder objOrder = SortOrder.None;
                if (sColumnSort != null && Enum.TryParse<SortOrder>(sColumnSort, out objOrder))
                    objColumn.HeaderCell.SortGlyphDirection = objOrder;
            }
        }

        private void SaveSettings(UIConfigSaver.WindowPositionSettings objSettings)
        {
            foreach (DataGridViewColumn objColumn in grdIssues.Columns)
            {
                objSettings.SetProperty(objColumn.Name + "_width", objColumn.Width);
                objSettings.SetProperty(objColumn.Name + "_sort", objColumn.HeaderCell.SortGlyphDirection.ToString());
            }
        }

        #endregion

        #region Timer Methods

        private void StartTimer()
        {
            timerWorkingIssue.Start();
        }

        private void StopTimer()
        {
            timerWorkingIssue.Stop();
        } 

        #endregion

        #region Working Issue Methods

        private void ChangeWorkingIssue(Issue objIssue)
        {
            RedmineClient.ChangeWorkingIssue(objIssue);

            lblCurrentlyWorking.Text = String.Format("{0} - {1}", objIssue.Id, objIssue.Subject);
            lblProjectName.Text = objIssue.Project.Name;
            lblTime.Text = "00:00:00";

            ShowWorkingIssueLabels();
            StartTimer();

            ReloadIssues();
        }

        private void CloseWorkingIssue()
        {
            RedmineClient.CloseWorkingIssue();

            StopTimer();
            lblCurrentlyWorking.Text = "(none)";
            HideWorkingIssueLabels();            

            ReloadIssues();
        }

        private void StopWorkingIssue()
        {
            RedmineClient.StopWorkingIssue();

            StopTimer();
            lblCurrentlyWorking.Text = "(none)";
            HideWorkingIssueLabels();

            ReloadIssues();
        } 

        private void ShowWorkingIssueLabels()
        {
            lblProjectName.Visible = true;
            lblProjectLabel.Visible = true;
            lblTime.Visible = true;
            btnStop.Visible = true;
            btnClose.Visible = true;
        }

        private void HideWorkingIssueLabels()
        {
            lblProjectName.Visible = false;
            lblProjectLabel.Visible = false;
            lblTime.Visible = false;
            btnStop.Visible = false;
            btnClose.Visible = false;
        }

        #endregion

        #region Events

        private IList<ComparableIssue> GetDataSource()
        {
            return ((grdIssues.DataSource as BindingSource).DataSource as SimpleFilteredList<ComparableIssue>);
        }

        private void grdIssues_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex < 0)
                return;

            if (grdIssues.Columns[e.ColumnIndex] == colStartWorking)
            {
                Issue objIssue = GetDataSource()[e.RowIndex].Original;

                ChangeWorkingIssue(objIssue);
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            StopWorkingIssue();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            CloseWorkingIssue();
        }

        private void timerWorkingIssue_Tick(object sender, EventArgs e)
        {
            try
            {
                if (RedmineClient.HasWorkingIssue())
                {
                    TimeSpan objSpan = RedmineClient.GetCurrentTimeWorking();
                    lblTime.Text = String.Format("{0:00}:{1:00}:{2:00}", objSpan.Hours, objSpan.Minutes, objSpan.Seconds);
                }
            }
            catch { }
        }

        #endregion
    }
}
